/*
 * @Description: 异常报告
 * @Author: KangLin
 * @Date: 2018-08-27 17:47:44
 * @Copyright: Created by Panxsoft.
 */

/**
 * 获取文件名
 * @param {*} uri
 */
function extractFileByUri(uri) {
	if (uri) {
		// return `${uri.split('/').pop()}.map`
		return `${uri}.map`;
	}
	return null;
}

const BASE_URL = 'http://localhost:3000/';

class ErrorReport {
	constructor(config) {
		if (!config) {
			throw new Error('config invalid');
		}
		this.stackDeep = config.stackDeep || 5;
		this.baseUrl = config.baseUrl || BASE_URL;
		this.projectName = config.baseUrl || '';
		this.image = null;
		// this.errorQueue = []; // 错误队列
	}

	/**
     * script 脚本加载错误
     * @param {*} param0
     */
	loadError({
		request, type, message, stack,
	}) {
		const fileUrl = extractFileByUri(request);
		const queryString = `fileurl=${fileUrl}&request=${request}&type=${type}&message=${message}&stack=${this.extractErrorStack(stack)}`;
		// this.errorQueue.push(queryString);
		this.send('loadScript', queryString);
	}

	/**
     * 运行时错误
     * @param {*}
     */
	runtimeError({
		fileurl, line, column, message, stack,
	}) {
		const queryString = `fileurl=${fileurl}&line=${line}&column=${column}&message=${message}&stack=${stack}`;
		// this.errorQueue.push(queryString);
		this.send('runtime', queryString);
	}

	/**
     * 把错误 stack 转成数组形式
     * @param {*} stack
     */
	parseErrorStack(stackMessage) {
		const stacks = [];
		const stackItems = stackMessage.split(/at\s+/);
		const deep = Math.min(this.stackDeep, stackItems.length); // 最大deep
		for (let i = 1; i < deep; i += 1) {
			// 获取包含url、line、col的部分
			const infoString = stackItems[i].replace(/^.+\(/, '').replace(/\)\s+?$/, '');
			const infoArray = infoString.split(':');
			const column = infoArray.pop();
			const line = infoArray.pop();
			const url = infoArray.join(':');
			const fileurl = extractFileByUri(url);
			stacks.push({
				fileurl,
				line,
				column,
			});
		}
		return stacks;
	}

	/**
     * 提交错误
     * @param {*} url
     */
	send(type, queryString, cb) {
		if (!this.image) {
			this.image = new Image();
		}
		this.image.src = `${this.baseUrl + type}/?project=${this.projectName}&${queryString}`;
		if (typeof cb === 'function') {
			this.image.onload = cb;
		}
	}

	/**
     *
     * @param {*} error
     */
	extractErrorStack(stackMessage) {
		if (stackMessage.indexOf(' at ')) {
			const stackItems = this.parseErrorStack(stackMessage);
			return JSON.stringify(stackItems);
		}
		return '';
	}

	init() {
		/**
         * 监听全局error事件
         * @param {String} errorMessage
         * @param {String} scriptURI
         * @param {number} lineNo
         * @param {number} columnNo
         * @param {String} error
         */
		window.onerror = (errorMessage, scriptURI, lineNo, columnNo, error) => {
			lineNo = lineNo || (window.event && window.event.errorCharacter) || null;
			const fileurl = extractFileByUri(scriptURI);
			this.runtimeError({
				fileurl: fileurl || null,
				line: lineNo,
				column: columnNo || null,
				message: errorMessage || null,
				stack: this.extractErrorStack(error.stack),
			});
		};
	}
}

const report = new ErrorReport({});
report.init();
